<?php

namespace App\Console\Commands\Fix;

use App\Common\Libs\Ali\Oss;
use App\Common\Libs\Json;
use App\Console\BaseCommand;
use App\Consts\GlobalConst;
use App\Consts\GlobalMessageConst;
use App\Consts\GlobalReplyConst;
use App\Consts\GlobalUploadConst;
use App\Models\UserMessageCommentReceive;
use App\Models\UserMessageCommentSend;
use Illuminate\Database\Query\Builder;

/**
 * 评论 OSS 文件修复
 * Class LikeFixCommand
 * @package App\Console\Commands\Fix
 */
class OssCommentFixCommand extends BaseCommand
{

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'fix:oss-comment {action}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'fix comment static message to oss';

    /**
     * 消息静态化 - 收到的评论
     * @return int
     */
    public function receive()
    {
        $subMode = $this->_getReceiveSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $messageId = $item->message_id;
                $userId = $item->receive_id;
                // 跳过自己的
                if ($item->sender_id == $item->receive_id) {
                    continue;
                }
                // get oss data
                $data = Oss::getInstance(GlobalUploadConst::OBJECT_COMMENT_MSG_RECEIVE)
                    ->getObject($userId . '/'. $messageId . '.json');
                $json = Json::decode($data, false);
                // get static data
                $message = UserMessageCommentReceive::getModel($userId)->where(['message_id' => $messageId])->first();
                $data = $this->_getStaticData($message);
                // 数据内容不同，重新上传
                if (Json::encode($json) != Json::encode((object)$data)) {
                    $res = false;
                    if ($data) {
                        $res = Oss::getInstance(GlobalUploadConst::OBJECT_COMMENT_MSG_RECEIVE . $userId . '/')
                            ->uploadTarget($data);
                    }
                    // log info
                    if (!$res) $this->logger('upload to oss failed - '. json_encode($data), true, 'script');
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] generate oss file [comment/receive] [$res] [".env('APP_ENV')."] : "
                        .GlobalUploadConst::OBJECT_COMMENT_MSG_RECEIVE."$userId/$messageId.json .";
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check oss file [comment/receive] : " ."$userId/$messageId.json .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'message_id');
        return 1;
    }

    /**
     * 消息静态化 - 发出的评论
     * @return int
     */
    public function send()
    {
        $subMode = $this->_getSendSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $messageId = $item->message_id;
                $userId = $item->sender_id;
                // get oss data
                $data = Oss::getInstance(GlobalUploadConst::OBJECT_COMMENT_MSG_SEND)
                    ->getObject($userId . '/'. $messageId . '.json');
                $json = Json::decode($data, false);
                // get static data
                $message = UserMessageCommentSend::getModel($userId)->where(['message_id' => $messageId])->first();
                $data = $this->_getStaticData($message);
                // 数据内容不同，重新上传
                if (Json::encode($json) != Json::encode((object)$data)) {
                    $res = false;
                    if ($data) {
                        $res = Oss::getInstance(GlobalUploadConst::OBJECT_COMMENT_MSG_SEND . $userId . '/')
                            ->uploadTarget($data);
                    }
                    // log info
                    if (!$res) $this->logger('upload to oss failed - '. json_encode($data), true, 'script');
                    $res = $res ? 'SUCCESS' : 'FAILED';
                    $info = "[$index/$finish] generate oss file [comment/send] [$res] [".env('APP_ENV')."] : "
                        .GlobalUploadConst::OBJECT_COMMENT_MSG_SEND."$userId/$messageId.json .";
                    $this->logger($info, true, 'script');
                } else {
                    $info = "[$index/$finish] check oss file [comment/send] : " ."$userId/$messageId.json .";
                    $this->info($info);
                }
                $index++;
            }
        }, 'message_id');
        return 1;
    }

    /**
     * 获取静态数据 - 发出的评论|收到的评论
     * @param UserMessageCommentSend|UserMessageCommentReceive $message
     * @return array
     */
    private static function _getStaticData($message)
    {
        $result = [];
        $target = [];
        $articleService = service()->ArticleService;
        $noteService = service()->NoteService;
        if ($message->type == GlobalMessageConst::MSG_TYPE_REPLY) {
            $reply = $message->reply;
            if (empty($reply)) return [];
            $user = $reply->user;
            if ($reply->type == GlobalReplyConst::REPLY_TYPE_COMMENT) {
                $comment = $reply->comment;
                $commentUser = $comment->user;
                $child = [
                    'id' => $comment->comment_id,
                    'content' => $comment->content,
                    'target_type' => GlobalConst::TARGET_TYPE_COMMENT,
                    'user' => [
                        'id' => $commentUser->user_id,
                        'nickname' => $commentUser->nickname,
                        'avatar' => $commentUser->avatar
                    ],
                ];
            } else {
                $toReply = $reply->toReply;
                $toUser = $reply->toUser;
                $child = [
                    'id' => $toReply->reply_id,
                    'content' => $toReply->content,
                    'target_type' => GlobalConst::TARGET_TYPE_REPLY,
                    'user' => [
                        'id' => $toUser->user_id,
                        'nickname' => $toUser->nickname,
                        'avatar' => $toUser->avatar
                    ],
                    'to_user' => [
                        'id' => $user->user_id,
                        'nickname' => $user->nickname,
                        'avatar' => $user->avatar
                    ],
                ];
            }
            if ($reply->target_type == GlobalConst::TARGET_TYPE_NOTE) {
                $target['note'] = $noteService->getNoteOne($reply->target_id);
                $target['target_type'] = GlobalConst::TARGET_TYPE_NOTE;
            }
            if ($reply->target_type == GlobalConst::TARGET_TYPE_DYNAMIC) {
                if (!empty($reply->dynamic)) {
                    if ($reply->dynamic->target_type == GlobalConst::TARGET_TYPE_ARTICLE) {
                        $article = $articleService->getArticleByArticleId($reply->dynamic->target_id);
                        $target['dynamic']['article'] = $article ? $article->toArray() : [];
                        $target['dynamic']['id'] = $reply->dynamic->dynamic_id;
                        $target['target_type'] = GlobalConst::TARGET_TYPE_DYNAMIC;
                        $target['dynamic']['type'] = $reply->dynamic->type;

                    }
                    if ($reply->dynamic->target_type == GlobalConst::TARGET_TYPE_NOTE) {
                        $target['dynamic'] = $noteService->getNoteOne($reply->dynamic->target_id);
                        $target['target_type'] = $reply->dynamic->target_type;
                        $target['dynamic']['type'] = $reply->dynamic->type;

                    }

                }
            }
            $result = [
                'id' => $message->message_id,
                'created_at' => $message->created_at,
                'main' => [
                    'id' => $reply->reply_id,
                    'content' => $reply->content,
                    'target_type' => GlobalConst::TARGET_TYPE_REPLY,
                ],
                'child' => $child,
                'target' => $target
            ];
        }
        if ($message->type == GlobalMessageConst::MSG_TYPE_COMMENT) {
            $comment = $message->comment;
            if ($comment->target_type == GlobalConst::TARGET_TYPE_NOTE) {
                $target['note'] = $noteService->getNoteOne($comment->target_id);
                $target['target_type'] = GlobalConst::TARGET_TYPE_NOTE;

            }
            if ($comment->target_type == GlobalConst::TARGET_TYPE_DYNAMIC) {
                if (!empty($comment->dynamic)) {
                    if ($comment->dynamic->target_type == GlobalConst::TARGET_TYPE_ARTICLE) {
                        $article = $articleService->getArticleByArticleId($comment->dynamic->target_id);
                        $target['dynamic']['article'] = $article ? $article->toArray() : [];
                        $target['dynamic']['type'] = $comment->dynamic->type;
                        $target['dynamic']['id'] = $comment->dynamic->dynamic_id;
                        $target['target_type'] = GlobalConst::TARGET_TYPE_DYNAMIC;
                    }
                    if ($comment->dynamic->target_type == GlobalConst::TARGET_TYPE_NOTE) {
                        $target['dynamic'] = $noteService->getNoteOne($comment->dynamic->target_id);
                        $target['dynamic']['type'] = $comment->dynamic->type;
                        $target['target_type'] = $comment->dynamic->target_type;
                    }
                }
            }
            $result = [
                'id' => $message->message_id,
                'created_at' => $message->created_at,
                'main' => [
                    'id' => $comment->comment_id,
                    'content' => $comment->content,
                    'target_type' => GlobalConst::TARGET_TYPE_COMMENT,
                ],
                'child' => [],
                'target' => $target
            ];
        }
        if (empty($result['child'])){
            $result['child'] = (object)[];
        }
        if (empty($result['target'])){
            $result['target'] = (object)[];
        }
        return $result;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getReceiveSubModel()
    {
        $subMode = UserMessageCommentReceive::getSubModel(function (Builder $query) {
            $query->where('message_id', '<>', '');
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'message_id', 'receive_id', 'sender_id', 'comment_id']);
        return $subMode;
    }

    /**
     * get sub model
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getSendSubModel()
    {
        $subMode = UserMessageCommentSend::getSubModel(function (Builder $query) {
            $query->where('message_id', '<>', '');
            $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        }, ['id', 'message_id', 'receive_id', 'sender_id', 'comment_id']);
        return $subMode;
    }

}
